#include "stdafx.h"
#include "SobolSequenceGenerator.h"

namespace RayTracePro
{
	const double SobolGenerator::inv2p32 = 1.0 / (1LL<<32);

	const unsigned int V0[] = 
	{
		0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x8000000, 
		0x4000000, 0x2000000, 0x1000000, 0x800000, 0x400000, 0x200000, 0x100000, 
		0x80000, 0x40000, 0x20000, 0x10000, 0x8000, 0x4000, 0x2000, 0x1000, 0x800,
		0x400, 0x200, 0x100,0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1
	};
	const unsigned int V1[] = 
	{
		0x80000000, 0xc0000000, 0xa0000000, 0xf0000000, 0x88000000, 
		0xcc000000, 0xaa000000, 0xff000000, 0x80800000, 0xc0c00000, 0xa0a00000, 
		0xf0f00000, 0x88880000, 0xcccc0000, 0xaaaa0000, 0xffff0000, 0x80008000, 
		0xc000c000, 0xa000a000,0xf000f000, 0x88008800, 0xcc00cc00, 0xaa00aa00, 
		0xff00ff00, 0x80808080, 0xc0c0c0c0, 0xa0a0a0a0, 0xf0f0f0f0, 0x88888888, 
		0xcccccccc, 0xaaaaaaaa, 0xffffffff
	};
	const unsigned int V2[] = 
	{
		0x80000000, 0xc0000000, 0x60000000, 0x90000000, 0xe8000000, 
		0x5c000000, 0x8e000000, 0xc5000000, 0x68800000, 0x9cc00000, 0xee600000, 
		0x55900000, 0x80680000, 0xc09c0000, 0x60ee0000, 0x90550000, 0xe8808000, 
		0x5cc0c000, 0x8e606000,0xc5909000, 0x6868e800, 0x9c9c5c00, 0xeeee8e00, 
		0x5555c500, 0x8000e880, 0xc0005cc0, 0x60008e60, 0x9000c590, 0xe8006868, 
		0x5c009c9c, 0x8e00eeee, 0xc5005555
	};

	int SobolGenerator::FirstZeroBitFromRight(unsigned int x)
	{
		int rs = 0;
		while (x & 1)
		{
			rs++;
			x>>=1;
		}
		return rs;
	}
	double SobolGenerator::NextX()
	{
		lastX = lastX ^ V0[FirstZeroBitFromRight(xId)];
		xId++;
		return lastX * inv2p32;
	}
	double SobolGenerator::NextY()
	{
		lastY = lastY ^ V1[FirstZeroBitFromRight(yId)];
		yId++;
		return lastY * inv2p32;
	}
	double SobolGenerator::NextZ()
	{
		lastZ = lastZ ^ V2[FirstZeroBitFromRight(zId)];
		zId++;
		return lastZ * inv2p32;
	}
}